#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <memory>
#include <unistd.h>
#include <sys/epoll.h>
#include "eventloop.hpp"

class Channel {
    private:
        using EventCallback = std::function<void()>;
        int _fd;
        EventLoop *_loop;
        uint32_t _events;
        uint32_t _revents;
        EventCallback _read_callback;/*可读事件回调*/
        EventCallback _write_callback;/*可写事件回调*/
        EventCallback _error_callback;/*错误事件回调*/
        EventCallback _close_callback;/*关闭事件回调*/
    public:
        Channel::Channel(EventLoop *loop, int fd):_loop(loop), _fd(fd), _events(0), _revents(0){}
        int Channel::fd() { return _fd; }
        uint32_t Channel::events() { return _events; };
        void Channel::set_read_callback(const EventCallback &cb) { _read_callback = cb; }
        void Channel::set_write_callback(const EventCallback &cb) { _write_callback = cb; }
        void Channel::set_error_callback(const EventCallback &cb) { _error_callback = cb; }
        void Channel::set_close_callback(const EventCallback &cb) { _close_callback = cb; }
        void Channel::remove() { return _loop->remove_channel(this); }
        void Channel::update() { return _loop->update_channel(this); }
        void Channel::set_revents(uint32_t events) { _revents = events; }
        void Channel::enable_read() { _events |= EPOLLIN; update(); }
        void Channel::disable_read() { _events &= ~EPOLLIN; update(); }
        void Channel::enable_write() { _events |= EPOLLOUT; update(); }
        void Channel::disable_write() { _events &= ~EPOLLOUT; update(); }
        void Channel::disable_all() { _events = 0; update(); }
        bool Channel::readable() { return _events & EPOLLIN; }
        bool Channel::writeable() { return _events & EPOLLOUT; }
        EventLoop *Channel::owner_loop() { return _loop; }
        void Channel::handle_event() {
            if (_revents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
                if (_read_callback) _read_callback();
            }
            if (_revents & EPOLLOUT) {
                if (_write_callback) _write_callback();
            }
            if (_revents & EPOLLERR) {
                if (_error_callback) _error_callback();
            }
            if (_revents & EPOLLHUP) {
                if (_close_callback) _close_callback();
            }
            return ;
        }
};